package dynamojunit;

import java.util.*;

import cloudjunit.JunitWorkFlowState;

import com.amazonaws.services.dynamodb.model.*;

public class WorkflowTable
{
	public static final String TABLE_NAME = "WorkflowTable"; 
	public static final String TABLE_KEY = "wfid";
	
	public static final String FINAL_RES_NOTFINISHED = "NOTFINISHED";
	public static final String FINAL_RES_ALLOK = "ALLOK";
	public static final String FINAL_RES_SOMEFAILED = "SOMEFAILED";
	
	public static final String TOTAL_NUMBER_OF_TESTS_TABLE_KEY = "totalNumberOfTests";
	public static final String TOTAL_NUMBER_OF_PASSED_TESTS_TABLE_KEY = "totalNumberOfPassedTests";
	public static final String TOTAL_NUMBER_OF_FAILED_TESTS_TABLE_KEY = "totalNumberOfFailedTests";
	public static final String WORKFLOW_STATUS_TABLE_KEY = "wfStatus";
	public static final String TEST_CLASSES_IDS_LIST_KEY = "tcidList";
	
	public WorkflowTable(boolean shouldInitTable)
	{
		if (shouldInitTable)
		{
			DynamoDbCommon.initTable(TABLE_NAME, TABLE_KEY);
		}
	}
	
	public Map<String,AttributeValue> readWorkflowEntry(String wfid)
	{
		return DynamoDbCommon.readUniqueEntry(TABLE_NAME, TABLE_KEY, wfid);
	}
	
	public String readWorkFlowStatus(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, WORKFLOW_STATUS_TABLE_KEY);
		if (val!=null)
			return val.getS();
		else
			return "";
	}
	
	public List<String> readTestClassesIdsList(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, TEST_CLASSES_IDS_LIST_KEY);
		if (val!=null)
			return val.getSS();
		else
			return new ArrayList<String>();
	}
	
	public String readWorkFlowTotalNumberOfTests(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, TOTAL_NUMBER_OF_TESTS_TABLE_KEY);
		if (val!=null)
			return val.getN();
		else
			return "";
	}
	
	public String readNumberOfPassedTests(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, TOTAL_NUMBER_OF_PASSED_TESTS_TABLE_KEY);
		if (val!=null)
			return val.getN();
		else
			return "";
	}
	
	public String readNumberOfFailedTests(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, TOTAL_NUMBER_OF_FAILED_TESTS_TABLE_KEY);
		if (val!=null)
			return val.getN();
		else
			return "";
	}
	
	
	
	public void startWorkflowEntry(String wfid)
	{
		// {key: wfid}, {start timestamp}, {end timestamp}, {status: INITIAL/RUNNING/FINISHED}, {final result: NOTFINISHED/ALLOK/SOMEFAILED}, {# of test classes }, {LIST of tcid}
		
		Date dateNow = new Date();
		Map<String, AttributeValue> item = newItem(wfid, dateNow.getTime(), JunitWorkFlowState.INITIAL, FINAL_RES_NOTFINISHED);
		DynamoDbCommon.putItemWithConsistency(TABLE_NAME, TABLE_KEY, item);
	}
	
	public boolean isWorkFlowIdExist(String wfid)
	{
		return DynamoDbCommon.isMatchingEntryExist(TABLE_NAME, TABLE_KEY, wfid);
	}
	
    private static Map<String, AttributeValue> newItem(String wfid, long startTime, String wfStatus, String finalResult)
    {
        Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
        
        item.put(TABLE_KEY, new AttributeValue(wfid));
        item.put("startTime", new AttributeValue().withN(Long.toString(startTime)));
        item.put(WORKFLOW_STATUS_TABLE_KEY, new AttributeValue(wfStatus));
        item.put("finalResult", new AttributeValue(finalResult));
        
        // other attribs - not yet

        return item;
    }
    
    //////////////////////////////
	
	public void updateTestClasses(String wfid, String... testClassesNames)
	{
		Key key = new Key(new AttributeValue(wfid));
		Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
		updates.put("testClassesNum", new AttributeValueUpdate(new AttributeValue().withN(Integer.toString(testClassesNames.length)), "PUT"));
		
		// Convert testClassesNames to tcids
		String tcids[] = testClassesNames.clone();	// clone so not to change the input array
		for (int i=0; i < tcids.length; ++i)
			tcids[i] = DynamoDbCommon.convertTestClassToTCID(tcids[i], wfid);

		updates.put(TEST_CLASSES_IDS_LIST_KEY, new AttributeValueUpdate(new AttributeValue().withSS(tcids), "PUT"));
		
		DynamoDbCommon.updateItem(TABLE_NAME, key, updates);
	}
	
	
	public void updateTotalNumberOfTests(String wfid, int totalNumberOfTests)
	{
		Key key = new Key(new AttributeValue(wfid));
		Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
		updates.put(TOTAL_NUMBER_OF_TESTS_TABLE_KEY, new AttributeValueUpdate(new AttributeValue().withN(Integer.toString(totalNumberOfTests)), "PUT"));
		
		DynamoDbCommon.updateItem(TABLE_NAME, key, updates);
	}
	
	public void updateFinalResultAndFinish(String wfid, String finalResult)
	{
		Key key = new Key(new AttributeValue(wfid));
		Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
		updates.put(WORKFLOW_STATUS_TABLE_KEY, new AttributeValueUpdate(new AttributeValue(JunitWorkFlowState.DONE), "PUT"));
		updates.put("finalResult", new AttributeValueUpdate(new AttributeValue(finalResult), "PUT"));
		Date dateNow = new Date();
		updates.put("endTime", new AttributeValueUpdate(new AttributeValue().withN(Long.toString(dateNow.getTime())), "PUT"));
		
		DynamoDbCommon.updateItem(TABLE_NAME, key, updates);
	}
	
	public void setWorkFlowState(String wfid, JunitWorkFlowState state)
	{
		Key key = new Key(new AttributeValue(wfid));
		Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
		updates.put(WORKFLOW_STATUS_TABLE_KEY, new AttributeValueUpdate(new AttributeValue(state.get_state()), "PUT"));
		
		DynamoDbCommon.updateItem(TABLE_NAME, key, updates);
	}
	
	public void updateNumericTestResults(String wfid, int numberOfPassedTests, int numberOfFailedTests)
	{
		Key key = new Key(new AttributeValue(wfid));
		Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
		updates.put(TOTAL_NUMBER_OF_PASSED_TESTS_TABLE_KEY, new AttributeValueUpdate(new AttributeValue().withN(Integer.toString(numberOfPassedTests)), "ADD"));
		updates.put(TOTAL_NUMBER_OF_FAILED_TESTS_TABLE_KEY, new AttributeValueUpdate(new AttributeValue().withN(Integer.toString(numberOfFailedTests)), "ADD"));
		
		DynamoDbCommon.updateItem(TABLE_NAME, key, updates);
	}
		
	
	/////////////////////////////////////////////////////////////
    // Examples:
	
    /*
	private void example()
	{
        // Scan items for movies with a year attribute greater than 1985
        HashMap<String, Condition> scanFilter = new HashMap<String, Condition>();
        Condition condition = new Condition()
            .withComparisonOperator(ComparisonOperator.GT.toString())
            .withAttributeValueList(new AttributeValue().withN("1985"));
        scanFilter.put("year", condition);
        ScanRequest scanRequest = new ScanRequest(TABLE_NAME).withScanFilter(scanFilter);
        ScanResult scanResult = DynamoDbCommon.dynamoDB.scan(scanRequest);
        System.out.println("Result: " + scanResult);
	}
	*/

	
}
